﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using MongoDB.Driver;
using Sustainalytics.BusinessResearchProductStates.Entities.ResearchState;
using Sustainalytics.ClientDW.Entities;
using Sustainalytics.Synchronization.Interface;
using Sustainalytics.Infrastructure.Common.ExtendedMethods;

namespace Sustainalytics.ClientDW.Synchronization.SyncRiskRatingsData.CorporateDataLogic
{
    public interface ICorporateDataProcessor
    {
        Task SetResearchInProgress(IEnumerable<Guid> companiesIds, bool isCoreRiskRatingResearch = false);
    }

    public class CorporateDataProcessor : ICorporateDataProcessor
    {
        private readonly ILogger logger;
        private readonly IMongoCollection<CorporateData> corporateDataCollection;
        private readonly IMongoCollection<CompanyProfileResearchState> researchStateCollection;

        public CorporateDataProcessor(
            IMongoCollection<CorporateData> corporateDataCollection, 
            IMongoCollection<CompanyProfileResearchState> researchStateCollection, 
            ILogger logger)
        {
            this.corporateDataCollection = corporateDataCollection;
            this.researchStateCollection = researchStateCollection;
            this.logger = logger;
        }

        async Task ICorporateDataProcessor.SetResearchInProgress(IEnumerable<Guid> companiesIds, bool isCoreRiskRatingResearch)
        {
            if (isCoreRiskRatingResearch)
            {
                await SetResearchInProgressState(companiesIds, cd => cd.CoreRiskResearchState.ResearchState, cprs => cprs.CoreRiskResearchState.ResearchState);
            }
            else
            {
                await SetResearchInProgressState(companiesIds, cd => cd.RiskRatingResearchState.ResearchState, cprs => cprs.RiskRatingResearchState.ResearchState);
            }
        }

        private async Task SetResearchInProgressState(
            IEnumerable<Guid> companyIds,
            Expression<Func<CorporateData, ResearchState>> corporateDataResearchStateField,
            Expression<Func<CompanyProfileResearchState, ResearchState>> companyProfileResearchStateField)
        {
            var callerMethod = new StackFrame(1).GetMethod().Name;

            var resetCorporateDataToResearchInProgress = Builders<CorporateData>.Update.Set(corporateDataResearchStateField, ResearchState.ResearchInProgress);

            var resetEsgResearchResult = await corporateDataCollection.UpdateManyAsync(cd => companyIds.Contains(cd.Id), resetCorporateDataToResearchInProgress).ConfigureAwait(false);

            logger.Log($"Set research state to {ResearchState.ResearchInProgress.GetEnumDescription()} for {resetEsgResearchResult.ModifiedCount} companies in " +
                        $"{typeof(CorporateData).Name} collection on behalf of {callerMethod} ");

            var resetCompanyProfileResearchStateToResearchInProgress = Builders<CompanyProfileResearchState>.Update.Set(companyProfileResearchStateField, ResearchState.ResearchInProgress);

            resetEsgResearchResult = await researchStateCollection.UpdateManyAsync(x => companyIds.Contains(x.Id), resetCompanyProfileResearchStateToResearchInProgress).ConfigureAwait(false);

            logger.Log($"Set research state to {ResearchState.ResearchInProgress.GetEnumDescription()} for {resetEsgResearchResult.ModifiedCount} companies in " +
                        $"{typeof(CompanyProfileResearchState).Name} collection on behalf of {callerMethod} ");
        }
    }
}
